/* 
?.  (可选链操作符)
● 语法: 表达式?.xxx  |  表达式?.()
● 左侧表达式的值可能是undefined或null, 或者可能不存在时, 结果为undefined, 不会抛出错误
*/
interface State {
  name?: string;
  fn?: () => {}
}

let s: State = {
  name: 'tom',
  fn:  () => {
    return 'abc'
  }
}
s.name?.length
s.fn?.()


/* 
?? (空值合并操作符)
● 语法: 表达式1 ?? 表达式2
● 用于在左侧操作数为 null 或 undefined 时，返回右侧操作数的值，否则返回左侧操作数。
● 区别于||: 左边操作数对应的boolean值为false时，返回右侧操作数的值，否则返回左侧操作数。
*/

const obj = {
  a: undefined,
  b: null
}

let a1 = obj.a ?? 'abc'
let a2 = obj.b ?? 0
let a3 = false ?? 'abc'

/* 
! (非空断言操作符)
● 语法: 表达式! 
● 告诉 TS编译器，左侧表达式不会为 null 或 undefined，从而避免编译器报告错误
*/
const container = document.getElementById("container")!
container.innerHTML


/* 
!. (非空断言链操作符)
● 表达式!.xxx = value
● 断言表达式不会为 null 或 undefined, 整个表达式可以可以被赋值
● ?.的表达式只能读取, 不能被赋值
?. 相当于if语句, 如果没有值, 不会报错  ==> 安全的
!. 直接认定不是null/undefined, 如果没值, 运行出错  ==> 不安全的
*/
const container2 = document.getElementById("container")
container2!.innerHTML = 'abc'
container2?.innerHTML